import re
import nltk
from nltk.corpus import wordnet as wn

month_names=["january","jan","february","feb","march","mar","april","apr","may","june","jun","july","jul","august","aug","september","sep","october","oct","november","nov","december","dec"]
week_names=["sunday","sun","monday","mon","tuesday","tue","wednesday","wed","thursday","thu","friday","fri","saturday","sat"]

DIGITNUM ="[0-9]+"
RE_DIGITNUM=re.compile(DIGITNUM)

def get_digit_numbers(string):
	"""returns all numbers in digit present in string"""
	return RE_DIGITNUM.findall(string)
	
def get_separate_word_numbers(string):
	"""returns a list of the form [ [num,loc],....]"""
	toks=nltk.word_tokenize(string)
	word_number_list=[]
	count=0
	for token in toks:
		if re.match(DIGITNUM,token)!= None:
			count+=1
			continue
		flag=0
		sn=wn.synsets(token)
		for i in sn:
			lemma=i.lemma_names
			for l in lemma:
				if re.match(DIGITNUM,l)!= None:
					flag=1
					word_number_list.append([token,count])
					break
			if flag==1:
				break
		count+=1

	return word_number_list
	
def get_logical_word_numbers(string):
	"""returns logical word numbers , eg: 'twenty three' """
	ret_list=get_separate_word_numbers(string)
	length=len(ret_list)
	i=0
	logical_word_list=[]
	added=1
	while i < length:
		if i==length-1:
			if added!=0:
				logical_word_list.append(ret_list[i])
				added=1
			break
		temp_str=ret_list[i][0]
		loc=ret_list[i][1]
		added=0
		for j in range(i+1,length):
			#print 'a-b=',ret_list[j][1] ,ret_list[j-1][1]
			if ( ret_list[j][1] - ret_list[j-1][1] ) == 1:
				temp_str=temp_str+" "+ret_list[j][0]
				i=j
			else:
				logical_word_list.append([temp_str,loc])
				i=j
				added=1
				break
		if added==0:
			logical_word_list.append([temp_str,loc])
	
	return logical_word_list

def modify_for_date(string):
	""" returns [toks,modify_list] where toks is the modified, tokenized string.
	modify_list is of the form [[modify_term("NUM_X"),actual_word,location],.....]
	"""
	modify_list=[]
	modify_term="NUM_X"
	toks=nltk.word_tokenize(string)
	logical_number_word_list=get_logical_word_numbers(string)
	for t in toks:
		for num_word in logical_number_word_list:
			if t== num_word[0]:
				toks[toks.index(t)]=modify_term
				modify_list.append([modify_term,t,num_word[1]])
				modify_term+="X"

	return [toks,modify_list]

# needs to consider all possibilites....work more to find them!!!!
def date_recognizer(string):
	""" extracts and dates from the string
	"""
	month="(january)|(jan)|(february)|(feb)|(march)|(mar)|(april)|(apr)|(may)|(june)|(jun)|(july)|(jul)|(august)|(aug)|(september)|(sep)|(october)|(oct)|(november)|(nov)|(december)|(dec)"
	week="(sunday)|(sun)|(monday)|(mon)|(tuesday)|(tue)|(wednesday)|(wed)|(thursday)|(thu)|(friday)|(fri)|(saturday)|(sat)"
	seperator=" |,|-|/|(of)|\."
	year_numf="(\d{4})"
	numf="(\d{1,2}[a-z]{0,2})|(NUM_[X]+)"
	
	date_rule1="("+numf+")("+seperator+")+("+month+")("+seperator+")+("+year_numf+")" #c=[b[1],b[6],b[32]]
	date_rule2="("+month+")("+seperator+")+("+numf+")("+seperator+")+("+year_numf+")" #c=[b[1],b[27],b[32]]
	date_rule3="("+numf+")("+seperator+")+("+numf+")("+seperator+")+("+year_numf+")"  #c=[b[1],b[6],b[11]]
	
	date_rule4="("+month+")("+seperator+")+("+year_numf+")"	#c=[b[1],b[27]]
	date_rule5="("+month+")("+seperator+")+("+numf+")"	#c=[b[1],b[27]]
	date_rule6="("+year_numf+")("+seperator+")+("+month+")"	#c=[b[1],b[6]]
	date_rule7="("+numf+")("+seperator+")+("+month+")"	#c=[b[1],b[6]]
	date_rule8=year_numf	#c=[b[1]]
	
	date_rules=[date_rule1,date_rule2,date_rule3,date_rule4,date_rule5,date_rule6,date_rule7,date_rule8]
	s=string.lower()
	tokenized_s,modify_list=modify_for_date(s)
	
	t_string=""
	for i in tokenized_s:
		t_string+=i
		t_string+=" "
	for rule in date_rules:
		ans=re.search(rule,t_string)
		if ans!=None:
			break
	
	if ans==None:
		return []
	#extract year, month and day
	b=re.split(rule,t_string)
	if rule==date_rule1:
		c=[b[1],b[6][:3],b[32]]
	elif rule==date_rule2:
		c=[b[27],b[1][:3],b[32]]
	elif rule==date_rule3:
		c=[b[1],b[6][:3],b[11]]
	elif rule==date_rule4:
		c=[-1,b[1][:3],b[27]]
	elif rule==date_rule5:
		c=[b[27],b[1][:3],-1]
	elif rule==date_rule6:
		c=[-1,b[6][:3],b[1]]
	elif rule==date_rule7:
		c=[b[1],b[6][:3],-1]
	elif rule==date_rule8:
		c=[-1,-1,b[1]]
	
	
	#print ans.group()
	#print ans.groups()
	if c[0]!=-1:
		tmp=re.search("\d+",c[0])
		tmp=tmp.group()
		tmp=int(tmp)%31
		c[0]=tmp
		
	ans_list_form=[str(c[0])[:2],str(c[1]),str(c[2])]

	for i in ans_list_form:
		if type(i)==str and i.find("NUM_X")>=0:
			for j in modify_list:
				if i==j[0]:
					ans_list_form[ans_list_form.index(i)]=j[1]
					break
	
	return [ans_list_form]

def month_recognizer(sent):
	"""detects if any month name is present in the sent
	"""
	t=sent.lower()
	m_list=[]
	for i in month_names:
		if t.find(i)!=-1:
			m_list.append([i[:3]])
	
	return m_list

def num_recognizer(sent):
	"""returns any no present in the sentence
	"""
	tmp=get_logical_word_numbers(sent)
	nums=[]
	for i in tmp:
		nums.append([i[0]])
	#now look for digits as well
	tmp=re.findall('\d+',sent)
	for i in tmp:
		nums.append([str(i)])
	return nums

def object_recognizer(sent):
	"""returns proper nouns as objects
	"""
	toks=nltk.word_tokenize(sent)
	tags=nltk.pos_tag(toks)
	obj_list=[]
	t=''
	flag=0
	for i in tags:
		if i[1].find('NNP')!= -1:
			if flag==0:
				t=i[0]
				t+=' '
				flag=1
			elif flag==1:
				t+=i[0]
				t+=' '
		elif flag==1:
			obj_list.append([t.rstrip()])
			flag=0
	if flag==1:
		obj_list.append([t.rstrip()])
	return obj_list


def get_named_entity(sent,ques_point):
	""" returns the named entities in sent, according to ques_point
	"""
	if ques_point=="DATE":
		return date_recognizer(sent)
	elif ques_point=='NUMBER':
		return num_recognizer(sent)
	elif ques_point=='TIME':
		return time_recognizer(sent)
	elif ques_point=='MONTH':
		return month_recognizer(sent)
	elif ques_point=='OBJECT':
		return object_recognizer(sent)
	else:
		print 'ner: cannot detect',ques_point
		return []
		
	
	
	
	
	
	
